package org.ccay.excel.exporter.util.impl;

import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.Selectors;
import org.ccay.core.exception.ApplicationException;
import org.ccay.core.io.FileStoreType;
import org.ccay.core.io.VFSFileObject;
import org.ccay.core.ioc.Ccay;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.log.ILogger;
import org.ccay.core.request.impl.RequestContext;
import org.ccay.core.util.StreamUtil;
import org.ccay.core.util.StringUtil;
import org.ccay.download.IDownloadSupport;
import org.ccay.excel.importer.internal.impl.ExcelMetaManager;
import org.ccay.excel.meta.ExcelMeta;
import org.ccay.excel.meta.IDynamicExcelMetaProvider;
import org.ccay.excel.meta.IExcelMetaManager;
import org.ccay.excel.util.impl.ExcelUtil;
import org.ccay.vfs.ApacheVFSFileObject;
import org.ccay.vfs.VFS;
import org.ccay.vfs.VFSException;



/**
 * 下载Excel导入模板
 * 
 * @author chaowangbang
 * 
 */
@Named("IDownloadSupport.ExcelTemplate")
public class ExcelTemplateDownload implements IDownloadSupport {
	@Inject
	public IExcelMetaManager excelMetaManager;
	
	/**
	 * 模板路径
	 */
	private final String TEMPLATE_PATH = "config/excel/";
	
	/** 日志记录器 **/
	private static ILogger logger = CcayLoggerFactory.getLogger(ExcelTemplateDownload.class);
	
	public boolean validatePrivilege(Map<String, String> map)
			throws ApplicationException {
		return true;
	}

	public VFSFileObject getFileInfo(Map<String, String> map)
			throws ApplicationException {
		//0----------基本变量定义
		// 获得模板类型
		final String excelType = map.get("excelType");
		//参数
		final Map<String, String> toMap = map;
		//参数摘要
		String md5 = getMd5(toMap);
		md5 = md5 == null ? "" : "("+md5+")";
		//基本名称
		String baseName = MessageFormat.format("{0}.template",excelType);
		
		//获取用户语言
		String language = "";
		if(RequestContext.getCurrent() != null &&  RequestContext.getCurrent().getUserLanguage()!=null){
			language = RequestContext.getCurrent().getUserLanguage();
		}
		language = language == null ? "_" : "_"+language;
		//返回值
		ApacheVFSFileObject fileInfo = null;
		//模板显示名称
		String displayName = MessageFormat.format("{0}{1}{2}.xlsx",baseName,(md5 == null ? "" : md5),language);
		//相对路径
		String relativePath = MessageFormat.format("/template/{0}",displayName);
		//模板文件信息
		fileInfo = new ApacheVFSFileObject(ExcelUtil.VFS_MODULE_EXCEL,relativePath,FileStoreType.TEMP);
		fileInfo.setDisplayName(displayName);
		if(!fileInfo.exists()){
			copyToTemp(fileInfo,excelType,language,md5,map);
		}else{
			logger.debug("Get template file from temp file cache! fileInfo : " + fileInfo);
		}
		return fileInfo;
	}
	
	protected void copyToTemp(ApacheVFSFileObject fileInfo,String excelType,String language,String md5,Map<String, String> map) throws ApplicationException{
		//1-----------先从classpath中找
		boolean isFound = copyClassPathTemplate(fileInfo,excelType,md5,language);
		if(isFound){
			return;
		}
		//2-----------生成
		OutputStream outputStream = null;
		try{
			logger.debug("Generate template file : " +  MessageFormat.format("{0}.template{1}{2}.xlsx",excelType,md5,language));
			excelMetaManager.generateExcelTemplate(getExcelMeta(excelType,map),fileInfo.getOutputStream());
		}finally{
			StreamUtil.closeStreams(outputStream);
		}
	}
	
	protected boolean copyClassPathTemplate(ApacheVFSFileObject fileInfo,String excelType,String md5,String language){
		//1、查找与参数摘要及当前语言匹配的模板
		URL url = ExcelMetaManager.class.getClassLoader().getResource(TEMPLATE_PATH+MessageFormat.format("{0}.template{1}{2}.xlsx",excelType,md5,language));
		//2、查找与参数摘要匹配的模板
		if(url == null){
			url = ExcelMetaManager.class.getClassLoader().getResource(TEMPLATE_PATH+MessageFormat.format("{0}.template{1}.xlsx",excelType,md5));
		}
		//3、查找与语言匹配的模板
		if(url == null){
			url = ExcelMetaManager.class.getClassLoader().getResource(TEMPLATE_PATH+MessageFormat.format("{0}.template{1}.xlsx",excelType,language));
		}
		//4、查找基本模板
		if(url == null){
			url = ExcelMetaManager.class.getClassLoader().getResource(TEMPLATE_PATH+MessageFormat.format("{0}.template.xlsx",excelType));
		}
		//模板定义在classpath中被找到
		if(url != null){
			FileObject classPathTemp = VFS.resolveFile(url.getPath().toString());
			try {
				fileInfo.getFileObject().copyFrom(classPathTemp,  Selectors.SELECT_ALL);
				logger.debug("Get template file from classpath : " + url.getPath().toString());
				return true;
			} catch (FileSystemException e) {
				throw new VFSException(e.getCode(),e.getMessage(),e);
			}
		}
		return false;
	}
	/**
	 * 生成参数摘要，作为模板缓存的KEY
	 * @param map
	 * @return
	 */
	private String getMd5(Map<String, String> map) {
		Map<String,String> extParamsMap = new HashMap<String,String>(map);
		//去掉通用参数
		extParamsMap.remove("excelType");
		extParamsMap.remove("dlType");
		//无扩展参数 返回空字符串。
		if(extParamsMap.isEmpty()){
			return null;
		}
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
			md.update(map.toString().getBytes("utf-8"));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return new BigInteger(1, md.digest()).toString(16);
	}
	
	/**
	 * 可以重写当前方法  达到动态模板下载
	 * @param excelType
	 * @return
	 * @throws ApplicationException
	 * Created：2013-7-20
	 * @author chaowangbang
	 */
	private ExcelMeta getExcelMeta(String excelType,Map<String, String> userMap) throws ApplicationException{
		ExcelMeta excelMeta = excelMetaManager.getExcelMeta(excelType);
		if(StringUtil.isNullOrEmpty(excelMeta.getDynamicProvider())){
			return excelMeta;
		}
		try {
			excelMeta = excelMeta.copy();
		} catch (CloneNotSupportedException e) {
			logger.error(e);
		}
		IDynamicExcelMetaProvider dynamicProvider = Ccay.getContext().getBean(excelMeta.getDynamicProvider(), IDynamicExcelMetaProvider.class);
		return dynamicProvider.process(excelMeta, userMap);
	}
	
	/**
	 * 获得下载类型
	 * 
	 * @return
	 */
	public String getDownloadType() {
		return "ExcelTemplate";
	}

}
